/**
 * Created by IntelliJ IDEA.
 * User: jiyufei
 * Date: 2018/11/9
 * Time: 11:07
 **/
package com.jiyufei.secure;

import com.jiyufei.bean.SecureAnalysedLog;
import com.jiyufei.bean.SecureLog;
import com.jiyufei.elasticsearch.ElasticSearchOpertator;
import com.jiyufei.util.ElasticSearchInfo;
import com.jiyufei.util.SecureSessionInfo;
import io.searchbox.core.SearchResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SecureAnalysis {
    
    
    private ElasticSearchOpertator elasticSearchOpertator;
    private SearchResult searchResult;
    private SecureLog secureLog;
    private Date queryStartTime;
    private String queryStartTimeStr,queryEndTimeStr;
    private List<SearchResult.Hit<SecureLog,Void>> hits;
    private SimpleDateFormat sdf;
    private String newQueryDsl;
    private long diffTime;
    private int step = SecureSessionInfo.QUERY_STEP;
    private int offsetTime = SecureSessionInfo.QUERY_OFFSET_TIME;
    private Pattern patternFirstWord,patternLoginSuccessful,patternUserInvalid,patternFailedPassword;
    private Matcher matcherFirstWord,matcher;
    private SecureAnalysedLog secureAnalysedLog;
    
    
    private String queryDsl = "{\n" +
            "    \"query\":{\n" +
            "        \"bool\":{\n" +
            "            \"must\":{\n" +
            "                \"match_all\":{}\n" +
            "            },\n" +
            "            \"filter\":{\n" +
            "                \"range\":{\n" +
            "                    \"time\":{\n" +
            "                        \"gt\": \"now-2m\",  \n" +
            "                        \"lt\": \"now\",\n" +
            "                        \"format\": \"yyyy-MM-dd HH:mm:ss\",\n" +
            "                        \"time_zone\": \"+0800\"\n" +
            "                    }\n" +
            "                }\n" +
            "            }\n" +
            "        }\n" +
            "    },\n" +
            "    \"sort\":[\n" +
            "        {\"time\":{\"order\":\"asc\"}},\n" +
            "        {\"offset\":\"asc\"}\n" +
            "        ],\n" +
            "    \"from\":0,\n" +
            "    \"size\":30\n" +
            "}";
    
    
    private final String regSSHFirstWord = "(\\S+)\\s.+";
    
    //Accepted password for root from 192.168.218.116 port 4928 ssh2
    private final String regSSHLoginSuccessful = "Accepted\\spassword\\sfor\\s(\\S+)\\sfrom\\s((\\d+\\.){3}\\d+)\\sport\\s(\\d+)(.+)";
    //Failed password for root from 42.7.27.164 port 56476 ssh2
    private final String regSSHLoginFailedPassword = "Failed\\spassword\\sfor\\s(\\S+)\\sfrom\\s((\\d+\\.){3}\\d+)\\sport\\s(\\d+)(.+)";
    //Invalid user butter from 81.7.171.64 port 48946
    private final String regSSHLoginUserInvalid = "Invalid\\suser\\s(\\S+)\\sfrom\\s((\\d+\\.){3}\\d+)\\sport\\s(\\d+)";
    
    
    
    
    
    
    private final static Logger logger = LoggerFactory.getLogger(SecureAnalysis.class);

    public SecureAnalysis(){
        elasticSearchOpertator = new ElasticSearchOpertator();
        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        queryStartTime = new Date();
        patternFirstWord = Pattern.compile(regSSHFirstWord);
        patternLoginSuccessful = Pattern.compile(regSSHLoginSuccessful);
        patternFailedPassword = Pattern.compile(regSSHLoginFailedPassword);
        patternUserInvalid = Pattern.compile(regSSHLoginUserInvalid);
        
    }
    
    //查询语句的时间管理器，间隔2分钟
    public String timeManager(){
        
        try {
            //校验起始时间，起始时间应小于当前时间-2min
            diffTime = (new Date().getTime() - queryStartTime.getTime())/(60*1000);
            if(diffTime < offsetTime+2){ //适当放宽时间
                Thread.sleep((Math.abs(diffTime)+2)*60*1000);
            }
            queryStartTimeStr = sdf.format(queryStartTime);
            queryEndTimeStr = sdf.format(queryStartTime.getTime() + (long)offsetTime*60*1000);
            newQueryDsl = queryDsl.replaceAll("gt\": \"now-2m","gt\": \"" + queryStartTimeStr);
            newQueryDsl = newQueryDsl.replaceAll("lt\": \"now","lt\": \"" + queryEndTimeStr);
            queryStartTime = sdf.parse(queryEndTimeStr);
            
            //System.out.println("[SecureAnalysis.timeManager]" + queryStartTimeStr + "--" + queryEndTimeStr);
            
        }catch (Exception e){
            e.printStackTrace();
            logger.error("[SecureAnalysis.timeManager]时间转换失败！" + e.getLocalizedMessage());
        }
        return newQueryDsl;
    }
    
    
    
/*
    public void checkLog(){
        int length = hits.size();
        String firstWord = null;
        for(int i=0;i<length;i++){
            secureLog = hits.get(i).source;
            secureLog.setId(hits.get(i).id);
            secureLog.setIndex(hits.get(i).index);
            if(secureLog.getProcess().compareTo("sshd") == 0){
                secureAnalysedLog = null;
                matcherFirstWord = patternFirstWord.matcher(secureLog.getMessage());
                if(matcherFirstWord.find()){
                    firstWord = matcherFirstWord.group(1);
                    switch (firstWord){
                        case "Accepted":
                            matcher = patternLoginSuccessful.matcher(secureLog.getMessage());
                            if(matcher.find()){
                                secureAnalysedLog = new SecureAnalysedLog();
                                secureAnalysedLog.setId(secureLog.getId());
                                secureAnalysedLog.setLogType("secure");
                                secureAnalysedLog.setType("ssh");
                                secureAnalysedLog.setTime(secureLog.getTime());
                                secureAnalysedLog.setSessionId(secureLog.getSessionId());
                                secureAnalysedLog.setHostIp(secureLog.getClientIp());
                                secureAnalysedLog.setUser(matcher.group(1));
                                secureAnalysedLog.setAttacksIp(matcher.group(2));
                                secureAnalysedLog.setPort(matcher.group(4));
                                secureAnalysedLog.setMsg("登录成功");
                                secureAnalysedLog.setMsgCode(100000);
                            }
                            break;
                        case "Invalid":
                            matcher = patternUserInvalid.matcher(secureLog.getMessage());
                            if(matcher.find()){
                                secureAnalysedLog = new SecureAnalysedLog();
                                secureAnalysedLog.setId(secureLog.getId());
                                secureAnalysedLog.setLogType("secure");
                                secureAnalysedLog.setType("ssh");
                                secureAnalysedLog.setTime(secureLog.getTime());
                                secureAnalysedLog.setSessionId(secureLog.getSessionId());
                                secureAnalysedLog.setHostIp(secureLog.getClientIp());
                                secureAnalysedLog.setUser(matcher.group(1));
                                secureAnalysedLog.setAttacksIp(matcher.group(2));
                                secureAnalysedLog.setPort(matcher.group(4));
                                secureAnalysedLog.setMsgCode(100001);
                                secureAnalysedLog.setMsg("使用不存在的用户名登录");
                            }
                            break;
                        case "Failed":
                            matcher = patternFailedPassword.matcher(secureLog.getMessage());
                            if(matcher.find()){
                                secureAnalysedLog = new SecureAnalysedLog();
                                secureAnalysedLog.setId(secureLog.getId());
                                secureAnalysedLog.setLogType("secure");
                                secureAnalysedLog.setType("ssh");
                                secureAnalysedLog.setTime(secureLog.getTime());
                                secureAnalysedLog.setSessionId(secureLog.getSessionId());
                                secureAnalysedLog.setHostIp(secureLog.getClientIp());
                                secureAnalysedLog.setUser(matcher.group(1));
                                secureAnalysedLog.setAttacksIp(matcher.group(2));
                                secureAnalysedLog.setPort(matcher.group(4));
                                secureAnalysedLog.setMsgCode(100002);
                                secureAnalysedLog.setMsg("登录密码错误");
                            }
                            break;
                    }
                }//类型判断
                //写入eleasticsearch
                if(secureAnalysedLog != null){
                    elasticSearchOpertator.insertSecureAnalysedLog(secureAnalysedLog);
                }
                
                
            }//ssh判断
        }
        
    }
    */
    
    public void analyseLog(){
        try {
        
            String myQueryDslFrom = null;
            //List<SearchResult.Hit<SecureLog,Void>> hits = null;
            String myQueryDsl = null;
        
            //无限循环
            while (true){
                myQueryDsl = timeManager();
                searchResult = elasticSearchOpertator.searchElasticSearch(myQueryDsl, ElasticSearchInfo.SecureIndex,ElasticSearchInfo.SecureType);
                hits = searchResult.getHits(SecureLog.class);
                int total = searchResult.getTotal().intValue();
                int offset = step;    //根据查询语句中的size字段设置
                //updateSessionId(hits);
                
                //System.out.println("[SecureAnalysis.analyseLog]total = " + total);
            
                //返回数量大于30，需要继续查询
                while(total > offset){
                    myQueryDslFrom = myQueryDsl.replaceAll("from\":0","from\":" + offset);
                    offset = offset + step;
                    searchResult = elasticSearchOpertator.searchElasticSearch(myQueryDslFrom, ElasticSearchInfo.SecureIndex,ElasticSearchInfo.SecureType);
                    hits = searchResult.getHits(SecureLog.class);
                    //updateSessionId(hits);
                }
            }
        
        
        
        
        }catch (Exception e){
            logger.error("[SecureAnalysis.analyseLog]操作出错！Err Msg:" + e.getLocalizedMessage());
        }
    }
    
    
    
    

}
